package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.CommonException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 
 * @since 2024-12-19
 */
@Service
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {


    @Autowired
    private IInteractionQuestionService questionService;


    /**
     * 新增回答或评论
     * @param dto
     */
    @Override
    public void insertReply(ReplyDTO dto) {

        InteractionReply reply = BeanUtils.copyBean(dto, InteractionReply.class);
        reply.setUserId(UserContext.getUser());
        boolean result = this.save(reply);
        if (!result){
            throw new DbException("更新数据库失败");
        }
        //判断是否是回答
        if (dto.getAnswerId() == null){
            //说明是回答，就修改问题表最近一次的回答id，并添加回答表的回答次数
            boolean resultForAnswer = questionService.lambdaUpdate()
                    .eq(InteractionQuestion::getId, dto.getQuestionId())
                    .set(InteractionQuestion::getLatestAnswerId, reply.getId())
                    .setSql("latest_answer_id = latest_answer_id + 1")
                    .update();
            if (!resultForAnswer){
                throw new DbException("更新数据库失败");
            }
        }else {
            //不是回答，就将评论的次数加以1
            boolean resultForReply = this.lambdaUpdate()
                    .eq(InteractionReply::getId, reply.getId())
                    .setSql("reply_times = reply_times + 1")
                    .update();
            if (!resultForReply){
                throw new DbException("更新数据库失败");
            }
        }

        //3.判断是否是学生提交
        //3.1是学生提交--isStudent为ture
        //修改问题表-questionId （管理端问题状态：0-未查看）
        questionService.lambdaUpdate()
                .eq(InteractionQuestion::getId, dto.getQuestionId())
                .set(dto.getIsStudent(), InteractionQuestion::getStatus, QuestionStatus.UN_CHECK)
                .update();
    }

    @Autowired
    private UserClient userClient;

    @Autowired
    private RemarkClient remarkClient;


    /**
     * 分页查询回答或评论列表
     * @param query
     * @return
     */
    @Override
    public PageDTO<ReplyVO> replyPage(ReplyPageQuery query) {
        if (query.getAnswerId() == null && query.getQuestionId() == null) {
            throw new CommonException("参数不合法");
        }
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(query.getQuestionId() != null, InteractionReply::getQuestionId, query.getQuestionId())
                .eq(query.getAnswerId() != null, InteractionReply::getAnswerId, query.getAnswerId())
                .eq(InteractionReply::getHidden,false)
                .page(query.toMpPage(
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)
                ));
        List<InteractionReply> records = page.getRecords();
        List<ReplyVO> list = new ArrayList<>();
        //使用stream流获得用户的id
        Set<Long> userSet = new HashSet<>();
        Set<Long> replySet = new HashSet<>();
        Set<Long> likeSet = new HashSet<>();
        for (InteractionReply record : records) {
            userSet.add(record.getUserId());
            userSet.add(record.getTargetUserId());
            replySet.add(record.getTargetUserId());
            likeSet.add(record.getId());
        }
        //查询用户是否点赞
        Set<Long> bizLiked = remarkClient.isBizLiked(likeSet);
        List<UserDTO> userDTOList = userClient.queryUserByIds(userSet);
        Map<Long, UserDTO> userMap = userDTOList.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        List<InteractionReply> replyList = listByIds(replySet);
        Map<Long, InteractionReply> replyMap = replyList.stream()
                .collect(Collectors.toMap(InteractionReply::getId, i -> i));
        for (InteractionReply record : records) {
            //封装返回值对象
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);
            //判断用户是否匿名
            UserDTO userDTO = userMap.getOrDefault(record.getAnswerId(), new UserDTO());
            if (!record.getAnonymity()){
                vo.setUserName(userDTO.getName());
            }
            UserDTO user = userMap.getOrDefault(record.getTargetUserId(), new UserDTO());
            //查询目标回复用户是否匿名replyMap
            InteractionReply reply = replyMap.getOrDefault(record.getTargetUserId(), new InteractionReply());
            if (reply.getAnonymity() != null && !reply.getAnonymity()){
                vo.setTargetUserName(user.getName());
            }else {
                vo.setTargetUserName(user.getName());
            }
            vo.setUserIcon(userDTO.getIcon());
            vo.setUserType(userDTO.getType());
            vo.setLiked(bizLiked.contains(record.getId()));
            list.add(vo);
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }


    /**
     * 管理端显示或隐藏评论
     * @param id
     * @param hidden
     * @return
     */
    @Override
    public void isHidden(Long id, Boolean hidden) {
        //判断当前评论或回复是否存在
        InteractionReply one = this.lambdaQuery().eq(InteractionReply::getId, id).one();
        if (ObjectUtils.isEmpty(one)){
            throw new BadRequestException("数据不存在");
        }
        boolean result = this.lambdaUpdate().eq(InteractionReply::getId, id)
                .set(InteractionReply::getHidden, hidden)
                .update();
        if (!result){
            throw new DbException("修改数据库失败");
        }
    }

    @Override
    public PageDTO<ReplyVO> replyPageAdmin(ReplyPageQuery query) {
        if (query.getAnswerId() == null && query.getQuestionId() == null) {
            throw new CommonException("参数不合法");
        }
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(query.getQuestionId() != null, InteractionReply::getQuestionId, query.getQuestionId())
                .eq(query.getAnswerId() != null, InteractionReply::getAnswerId, query.getAnswerId())
                .page(query.toMpPage(
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)
                ));
        List<InteractionReply> records = page.getRecords();
        List<ReplyVO> list = new ArrayList<>();
        //使用stream流获得用户的id
        Set<Long> userSet = new HashSet<>();
        for (InteractionReply record : records) {
            userSet.add(record.getUserId());
            userSet.add(record.getTargetUserId());
        }
        List<UserDTO> userDTOList = userClient.queryUserByIds(userSet);
        Map<Long, UserDTO> userMap = userDTOList.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        for (InteractionReply record : records) {
            //封装返回值对象
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);
            //判断用户是否匿名
            UserDTO userDTO = userMap.getOrDefault(record.getAnswerId(), new UserDTO());
            vo.setUserName(userDTO.getName());
            UserDTO user = userMap.getOrDefault(record.getTargetUserId(), new UserDTO());
            //查询目标回复用户是否匿名replyMap
            vo.setTargetUserName(user.getName());
            vo.setUserIcon(userDTO.getIcon());
            vo.setUserType(userDTO.getType());
            list.add(vo);
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }
}
